package com.wstuo.common.util;

import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;

import org.apache.commons.lang.StringUtils;
import org.apache.log4j.Logger;
/**
 * 
 * @author will
 *
 */
public class ReflectUtils {
	/**
	 * 默认分隔符
	 */
	public static final String DEFAUL_BREAK = "|";

	private static final Logger LOGGER = Logger.getLogger(ReflectUtils.class);
	
	/**
	 * 默认实现的一个方式，将当前类及父类的属性获取到，并反射到字符串；（如果有其他的实现，手动调用getValueByField 及 getFieldByAnnota ）
	 * @param obj
	 * @param clzAnnota
	 * @return
	 */
	public static StringBuffer getValueByAnnota(Object obj, Class clzAnnota) {
		StringBuffer allStr = new StringBuffer();
    	Class clz = obj.getClass() ;
    	List<Field> sList = getFieldByAnnota(clz, clzAnnota);
    	sList.addAll(getFieldByAnnota(clz.getSuperclass(), clzAnnota));
    	List<Object> r =getValueByField(obj, sList);
    	for (Object o : r) {
    		if (o != null) {
        		allStr.append(o).append(DEFAUL_BREAK);
			}
		}
    	LOGGER.debug("ReflectUtils.getValueByAnnota()"+allStr);
		return allStr;
	}
	/**
	 *  通过 类的  java.lang.reflect.Field 将obj对象的属性值反射出来；；
	 * @param obj
	 * @param fields
	 * @return
	 */
	
	public static List<Object> getValueByField(Object obj, List<Field> fields) {
		List<Object> r = new ArrayList<Object>();
		for (java.lang.reflect.Field f : fields) {
			boolean accessFlag = f.isAccessible();
            f.setAccessible(true);
            try {
				Object result = f.get(obj);
				r.add(result);
			} catch (Exception e) {
				LOGGER.error("ReflectUtils.getValueByField()",e); 
			}
            f.setAccessible(accessFlag);
		}
		return r;
	}
	
	/**
	 * 通过判断类的属性是否包含注解类，并将包含的 java.lang.reflect.Field 获取出来；
	 * @param clz 
	 * @param clzAnnota 
	 * @return
	 */
	public static List<Field> getFieldByAnnota(Class clz, Class clzAnnota) {
		List<Field> r = new ArrayList<Field>();
    	Field[] fields = clz.getDeclaredFields();
		for (java.lang.reflect.Field field : fields) {
			Object anno = field.getAnnotation(clzAnnota);
			if ( anno != null){
				r.add(field);
			}
		}
		return r;
	}
	public static List<String> getFieldNameByAnnota(Class clz, Class clzAnnota) {
		List<String> r = new ArrayList<String>();
    	Field[] fields = clz.getDeclaredFields();
		for (Field field : fields) {
			Object anno = field.getAnnotation(clzAnnota);
			if ( anno != null ){
				r.add(field.getName());
			}
		}
		return r;
	}
	/**
	 * 根据Field获取名字
	 * @param fields
	 * @return
	 */
	public static List<String> getNameByField(List<Field> fields) {
		List<String> list = new ArrayList<String>();
		if (fields != null) {
			for ( Field field : fields) {
				list.add(field.getName());
			}
		}
		return list;
	}
	
	/**
	 * 取得字段值
	 * 
	 * @param obj
	 * @param fieldName
	 * @return
	 */
	public static Object getFieldValue(Object obj, String fieldName) {
		return getFieldValue(obj, obj.getClass(), fieldName);
	}
	public static Object getSuperFieldValue(Object obj, String fieldName) {
		return getFieldValue(obj, obj.getClass().getSuperclass(), fieldName);
	}
	private static Object getFieldValue(Object obj,Class clz, String fieldName) {
		Object result = "";
		if (obj != null && fieldName != null && !"".equals(fieldName)) {
			try {
				java.lang.reflect.Field f = clz.getDeclaredField(fieldName);
	            boolean accessFlag = f.isAccessible();
	            f.setAccessible(true);
	            result = f.get(obj);
	            f.setAccessible(accessFlag);
			} catch (Exception e) {
				LOGGER.error("ReflectUtils.getFieldValue()",e); 
			}
		}
		return result;
	}
	
	
	/**
	 * 取得字段值
	 * 
	 * @param obj
	 * @param fieldName
	 * @return
	 */
	public static Object getFieldByName(Object obj, String fieldName) {
		Object result = null;
		if (obj != null && fieldName != null && !"".equals(fieldName)) {
			Class<?> clazz = obj.getClass();
			try {
				String methodname = "get" + StringUtils.capitalize(fieldName);
				Method method = clazz.getDeclaredMethod(methodname);
				method.setAccessible(true);
				result = method.invoke(obj);
			} catch (Exception e) {
				LOGGER.error("ReflectUtils.getValueByField()",e); 
				try {
					Field field = clazz.getDeclaredField(fieldName);
					field.setAccessible(true);
					result = field.get(obj);
				} catch (Exception e1) {
					LOGGER.error("ReflectUtils.getValueByField()",e1); 
				}
			}
		}
		return result;
	}
	/**
	 * 设置字段值
	 * 
	 * @param obj
	 * @param fieldName
	 * @return
	 */
	public static void setFieldByName(Object target, String fname,
			Class<?> fieldClass, Object fieldObj) {
		if (!fieldClass.isAssignableFrom(fieldObj.getClass())) {
			return;
		}
		Class<?> clazz = target.getClass();
		try {
			Method method = clazz.getDeclaredMethod(
					"set" + Character.toUpperCase(fname.charAt(0))
							+ fname.substring(1), fieldClass);
			method.setAccessible(true);
			method.invoke(target, fieldObj);
		} catch (Exception e) {
			LOGGER.error("ReflectUtils.getValueByField()",e); 
			try {
				Field field = clazz.getDeclaredField(fname);
				field.setAccessible(true);
				field.set(target, fieldObj);
			} catch (Exception e1) {
				LOGGER.error("ReflectUtils.getValueByField()",e1); 
			}
		}
	}
}